package main

import (
	"fmt"
	"io"
	"net"
	"strings"
	"time"
)

//用户角色
type User struct {
	Name   string
	Addr   string
	C      chan string //用来接受服务广播的消息
	conn   net.Conn    //用户与服务建立的链接
	Server *Server
}

type PriUser struct {
	//用来存储私聊姓名
	// var toUserName string
	PriName string
	// 用来存储私聊对象
	PriUser *User
}

func NewUser(conn net.Conn, server *Server) *User {
	addr := conn.RemoteAddr().String()
	user := &User{
		Name:   addr,
		Addr:   addr,
		C:      make(chan string),
		conn:   conn,
		Server: server,
	}

	// 开启go程监听消息
	go user.ListenMsg()
	return user
}

//随时监听接收服务发来的消息
func (u *User) ListenMsg() {
	for {
		//服务器发给用户的消息
		msg := <-u.C
		//将接受到的消息发送给客户端
		u.conn.Write([]byte(msg))
	}
}

//user 上线功能
func (u *User) Online() {

	//将用户添加到server.OnlineMap 中
	u.Server.Lock.Lock()
	u.Server.OnlineMap[u.Name] = u
	u.Server.Lock.Unlock()
	//将该用户上线的消息存入到server通道中
	u.Server.BroadCast(u, "上线了\n")
}

//user 下线功能
func (u *User) offline() {
	u.Server.Lock.Lock()
	u.Server.OnlineMap[u.Name] = u
	delete(u.Server.OnlineMap, u.Name)
	u.Server.Lock.Unlock()
	u.Server.BroadCast(u, "下了，拜拜")
	u.conn.Close()
}

//user 处理业务逻辑功能
func (u *User) HandlerServer() {
	//用来判断是否超时
	isLine := make(chan bool)

	go func() {

		priUser := new(PriUser)
		buf := make([]byte, 1024*4)
		for {
			n, err := u.conn.Read(buf)
			if n == 0 {
				u.offline()
				return
			}
			if err != nil && err != io.EOF {
				fmt.Println("conn.Read err:", err)
				return
			}
			msg := string(buf[:n-1])
			userMsg := priUser.PriName + msg

			isLine <- true
			// 		查看用户列表
			if userMsg == "who" {
				u.SendMsg("当前用户有：")
				u.Server.Lock.Lock()
				for userName, _ := range u.Server.OnlineMap {
					u.SendMsg(userName)
				}
				u.Server.Lock.Unlock()
				//修改用户姓名
			} else if len(userMsg) > 7 && strings.Contains(userMsg, "rename|") {
				newName := strings.Split(userMsg, "|")[1]
				u.Server.Lock.Lock()
				u.Server.OnlineMap[newName] = u
				delete(u.Server.OnlineMap, u.Name)
				u.Server.Lock.Unlock()
				u.Name = newName
				u.SendMsg(fmt.Sprintf("成功将姓名修改为：%s", newName))
				//私聊功能
			} else if len(userMsg) > 3 && strings.Contains(userMsg, "to|") {
				userName := strings.Split(userMsg, "|")[1]
				if strings.Count(userMsg, "|") == 1 {
					if user, ok := u.Server.OnlineMap[userName]; ok {
						u.SendMsg(fmt.Sprintf("开始跟%s私聊吧", userName))
						//确定私聊对象后将 对象姓名按一定格式保存
						priUser.PriName = fmt.Sprintf("to|%s|", userName)
						//同时将私聊对象保存起来
						priUser.PriUser = user
						priUser.PriUser.C <- fmt.Sprintf("即将有来自[%s]用户的私聊", u.Name)
					} else {
						u.SendMsg(fmt.Sprintf("%s不在线上", userName))
					}
				} else if strings.Count(userMsg, "|") == 2 {
					//私聊时 消息发送
					if msg != "exit" {
						priUser.PriUser.C <- msg
						//退出私聊时，将私聊对象跟对象姓名置为空
					} else {
						priUser.PriName = ""
						priUser.PriUser = new(User)
					}
				}
			} else {
				u.Server.BroadCast(u, userMsg)
			}
		}
	}()

	//超时强踢
	for {
		select {
		case <-isLine:
		case <-time.After(100 * time.Second):
			u.SendMsg("你因超时要被踢出去了")
			u.Server.Lock.Lock()
			delete(u.Server.OnlineMap, u.Name)
			u.Server.Lock.Unlock()
			u.conn.Close()
		}
	}
}

//用户自己给客户端发送消息
func (u *User) SendMsg(msg string) {
	u.conn.Write([]byte(msg + "\n"))
}
